var _Container = require('component/container.js');
var _inherit = require('core/inherit.js');
var HALF_SCREEN = 240;

function clip(x, min, max) {
    return x < min ? min : x > max ? max : x;
}
// ==========================
// Piece
// ==========================
function Piece(id, view, prew, nextw) {
    this.mId = id;
    this.mView = view;

    this.mPreviousWidth = prew;// when curren piece is in center of screen
    this.mNextWidth = nextw;

    this.mStart = 0;
    this.mDistance = 0;
}
Piece.prototype.getId = function () {
    return this.mId;
};
Piece.prototype.preWidth = function () {
    return this.mPreviousWidth;
};
Piece.prototype.nextWidth = function () {
    return this.mNextWidth;
};
Piece.prototype.setPrevious = function (p) {
    this.mPreviousWidth = p;
};
Piece.prototype.setPosition = function (p) {
    this.mView.getPosition()[0] = p;
    this.mView.touchMatrix();
};
Piece.prototype.getView = function () {
    return this.mView;
};
Piece.prototype.setNext = function (n) {
    this.mNextWidth = n;
};
Piece.prototype.setRange = function (start, dis) {
    this.mStart = start;
    this.mDistance = dis;
};
Piece.prototype.getStart = function () {
    return this.mStart;
};
Piece.prototype.getWidth = function () {
    return this.mDistance;
};
Piece.prototype.getPercent = function (dis) {
    return (dis - this.mStart) / this.mDistance;
};
Piece.prototype.resize = function (w, h) {
    this.mView.layoutVertical(h);
};
Piece.prototype.draw = function (context) {
    this.mView.draw(context);
};
Piece.prototype.toString = function () {
    return '[Piece id:' + this.mId + ', start:' + this.mStart + ']';
};

// ==========================
// Slide
// ==========================
function SlideStatus() {
    this.mPiece = 0;
    this.mDistance = 0;
    this.mPercent = 0;
}
SlideStatus.prototype.reset = function (piece, distance, percent) {
    this.mPiece = piece;
    this.mDistance = distance;
    this.mPercent = percent;
};
SlideStatus.prototype.getPiece = function () {
    return this.mPiece;
};
SlideStatus.prototype.getDistance = function () {
    return this.mDistance;
};
SlideStatus.prototype.getPercent = function () {
    return this.mPercent;
};

var _Constance = require('./constance.js');

// ==========================
// Slide
// ==========================
function SlideView() {
    _Container.call(this);
    this.mLocal = _Constance.getLocal();

    // draw star, end
    this.mDrawStart = 0;
    this.mDrawEnd = 0;
    this.mSegments = [];
    this.mPieces = [];

    // current movement
    this.mIndex = 0;
    this.mDistance = 0;

    this.setSize(480, 800);
}
_inherit(SlideView, _Container);
SlideView.prototype.mTag = 'SlideView';
SlideView.prototype.getPiece = function (index) {
    return this.mPieces[index];
};
SlideView.prototype.createStatus = function () {
    return new SlideStatus();
};
SlideView.prototype.addSegment = function (seg) {
    this.mSegments.push(seg);
    for (var i = 0, size = seg.size(); i < size; i++) {
        this.addChild(seg.getView(i));
    }
};
SlideView.prototype.getDistance = function () {
    return this.mDistance;
};
SlideView.prototype.layoutStart = function () {
    this.mIndex = 0;
    this.mDrawStart = 0;
    this.mDrawEnd = clip(1, 0, this.mPieces.length - 1);

    this.mDistance = this.mPieces[this.mIndex].getStart();
    this.mPieces[this.mDrawStart].setPosition(HALF_SCREEN);

    if (this.mDrawEnd > this.mDrawStart) {
        this.mPieces[this.mDrawEnd].setPosition(HALF_SCREEN + this.mPieces[this.mDrawStart].nextWidth());
    }
};
SlideView.prototype.layoutEnd = function () {
    this.mIndex = this.mPieces.length - 1;
    this.mDrawEnd = this.mIndex;
    this.mDrawStart = clip(this.mDrawEnd - 1, 0, this.mDrawEnd);

    this.mDistance = this.mPieces[this.mIndex].getStart();
    this.mPieces[this.mDrawEnd].setPosition(HALF_SCREEN);

    if (this.mDrawStart < this.mDrawEnd) {
        this.mPieces[this.mDrawStart].setPosition(HALF_SCREEN - this.mPieces[this.mDrawEnd].preWidth());
    }
};
SlideView.prototype.layoutView = function (index, distance) {
    var piece = this.mPieces[index];
    var percent = piece.getPercent(distance);
    if (percent < 0.5) {
        this.mDrawStart = clip(index - 1, 0, index);
        this.mDrawEnd = clip(index + 1, index, this.mPieces.length - 1);
    } else {
        this.mDrawStart = index;
        this.mDrawEnd = clip(index + 2, index, this.mPieces.length - 1);
    }

    var next = this.mPieces[index + 1];
    var start = HALF_SCREEN - next.preWidth() * percent;
    var end = HALF_SCREEN + piece.nextWidth() * (1 - percent);
    piece.setPosition(start);
    next.setPosition(end);

    var cursor = index;
    while (cursor > this.mDrawStart) {
        this.mPieces[cursor - 1].setPosition(start -= this.mPieces[cursor].preWidth());
        cursor--;
    }

    cursor = index + 1;
    while (cursor <= this.mDrawEnd - 1) {
        this.mPieces[cursor + 1].setPosition(end += this.mPieces[cursor].nextWidth());
        cursor++;
    }
};
SlideView.prototype.testout = function () {
    console.log('distance', this.mDistance);
    console.log('mIndex', this.mIndex);
    console.log('mDrawStart', this.mDrawStart);
    console.log('mDrawEnd', this.mDrawEnd);
};

/**
 * @param dis
 * @param sign +1,-1
 * @param status
 */
SlideView.prototype.getNextPiece = function (dis, sign, status) {
    this.moveTo(dis, status);

    // absorb with current position
    var percent = this.mPieces[this.mIndex].getPercent(this.mDistance);
    var next = clip(Math.floor(this.mIndex + percent + 0.5) + sign, 0, this.mPieces.length - 1);
    var np = this.mPieces[next];
    status.reset(np, np.getStart(), 0);
};
/**
 * @param dis
 * @param status
 */
SlideView.prototype.stopMove = function (dis, status) {
    this.moveTo(dis, status);

    var piece = this.mPieces[this.mIndex];
    var percent = piece.getPercent(this.mDistance);
    if (percent < 0.5) {
        status.reset(piece, piece.getStart(), 0);
    } else {
        var next = clip(this.mIndex + 1, 0, this.mPieces.length - 1);
        var np = this.mPieces[next];
        status.reset(np, np.getStart(), 0);
    }
};
SlideView.prototype.currentPiece = function () {
    return this.mPieces[this.mIndex];
};
SlideView.prototype.moveTo = function (dis, status) {
    var length = this.mPieces.length;
    if (length < 2) {
        this.mDistance = 0;
        this.layoutStart();
        status.reset(this.mPieces[0], 0, 0);
        return;
    }

    var current = this.mPieces[this.mIndex].getStart();
    var index = this.mIndex;
    if (dis >= current) {
        index++;// move to next
        while (index < length) {
            if (dis < this.mPieces[index].getStart()) {
                index--;
                break;
            }
            index++;
        }
        if (index == length) {
            this.layoutEnd();
        } else {
            this.layoutView(this.mIndex = index, this.mDistance = dis);
        }
    } else {
        while (index >= 0) {
            if (dis < this.mPieces[index].getStart()) {
                index--;
            } else {
                break;
            }
        }
        if (index == -1) {
            this.layoutStart();
        } else {
            this.layoutView(this.mIndex = index, this.mDistance = dis);
        }
    }

    var np = this.mPieces[this.mIndex];
    status.reset(np, this.mDistance, np.getPercent(this.mDistance));
    //console.log('moveto', this.mIndex, this.mDistance - this.mPieces[this.mIndex].getStart());
};
SlideView.prototype.setup = function () {
    var preoutscreen = 0;
    for (var i = 0; i < this.mSegments.length; i++) {
        var seg = this.mSegments[i];
        if (seg.size() == 0) {
            continue;
        }

        var start = this.mPieces.length;
        var stride = seg.stride();
        for (var s = 0, size = seg.size(); s < size; s++) {
            this.mPieces.push(new Piece(seg.getId(), seg.getView(s), stride, stride));
        }

        // link to previous piece
        if (start == 0) {// no previous
            this.mPieces[start].setPrevious(HALF_SCREEN);
        } else {
            this.mPieces[start].setPrevious(HALF_SCREEN + preoutscreen);
            this.mPieces[start - 1].setNext(HALF_SCREEN + seg.getMarginOut());
        }

        preoutscreen = seg.getMarginOut();
    }
    // set last.next
    this.mPieces[this.mPieces.length - 1].setNext(HALF_SCREEN);

    // bind to model
    var dis = HALF_SCREEN;
    for (var i = 0, pieces = this.mPieces, l = pieces.length - 1; i < l; i++) {
        var width = (pieces[i].nextWidth() + pieces[i + 1].preWidth()) * 0.5;
        pieces[i].setRange(dis, width);
        dis += width;
    }
    pieces[l].setRange(dis, HALF_SCREEN);
};
/**
 * @param w
 * @param h
 */
SlideView.prototype.resize = function (w, h) {
    this.setSize(w, h);
    for (var i = 0; i < this.mPieces.length; i++) {
        this.mPieces[i].resize(w, h);
    }
};
SlideView.prototype.drawContent = function (context) {
    for (var i = this.mDrawStart; i <= this.mDrawEnd; i++) {
        this.mPieces[i].draw(context);
    }
};

module.exports = SlideView;